package com.taijihuabao.common.emailutils;

import com.alibaba.druid.util.StringUtils;
import com.taijihuabao.common.exception.ServiceException;
import com.taijihuabao.common.jsonresult.ApplicationResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.List;

/**
 * @author changhui.tu
 */
@Slf4j
@Component
public class EmailUtils {

    /**
     * 默认编码
     */
    public static final String DEFAULT_ENCODING = "UTF-8";

    /**
     * 发送人
     */
    @Value("${spring.mail.username}")
    private String userName;

    @Resource
    private JavaMailSender mailSender;


    /**
     * 发送文本
     *
     * @param emailPojo:邮件pojo
     */
    public void sendSimpleTextMailActual(EmailPojo emailPojo) {
        //检验参数：邮件主题、收件人、邮件内容必须不为空才能够保证基本的逻辑执行
        if (StringUtils.isEmpty(emailPojo.getSubject()) || StringUtils.isEmpty(emailPojo.getContent())
                || CollectionUtils.isEmpty(emailPojo.getReceiver())) {
            throw new ServiceException(ApplicationResponseCode.ERROR);
        }
        log.info("开始发送简单文本邮件：主题->{}，收件人->{}，抄送人->{}，密送人->{}，附件->{}", emailPojo.getSubject(), emailPojo.getReceiver(), emailPojo.getCcPeoples(), emailPojo.getBccPeoples(), emailPojo.getAttachments());
        //附件处理，需要处理附件时，需要使用二进制信息，使用 MimeMessage 类来进行处理
        if (CollectionUtils.isNotEmpty(emailPojo.getAttachments())) {
            try {
                //附件处理需要进行二进制传输
                MimeMessage mimeMessage = mailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, DEFAULT_ENCODING);
                //设置邮件的基本信息：这些函数都会在后面列出来
                boolean continueProcess = handleBasicInfo(helper, emailPojo, false);
                //如果处理基本信息出现错误
                if (!continueProcess) {
                    log.error("邮件基本信息出错: 主题->{}", emailPojo.getSubject());
                    return;
                }
                //处理附件
                handleAttachment(helper, emailPojo.getSubject(), emailPojo.getAttachments());
                //发送该邮件
                mailSender.send(mimeMessage);
                log.info("发送邮件成功: 主题->{}", emailPojo.getSubject());
            } catch (MessagingException e) {
                e.printStackTrace();
                log.error("发送邮件失败: 主题->{}", emailPojo.getSubject());

            }
        } else {
            //创建一个简单邮件信息对象
            SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
            //设置邮件的基本信息
            handleBasicInfo(simpleMailMessage, emailPojo);
            //发送邮件
            mailSender.send(simpleMailMessage);
            log.info("发送邮件成功: 主题->{}", emailPojo.getSubject());
        }
    }

    /**
     * 公共方法，填充简单文本邮件基本信息
     *
     * @param simpleMailMessage:文本邮件信息对象
     * @param emailPojo                  : 邮件pojo
     */
    public void handleBasicInfo(SimpleMailMessage simpleMailMessage, EmailPojo emailPojo) {
        //设置发件人
        simpleMailMessage.setFrom(userName);
        //设置邮件的主题
        simpleMailMessage.setSubject(emailPojo.getSubject());
        //设置邮件的内容
        simpleMailMessage.setText(emailPojo.getContent());
        //设置邮件的收件人
        simpleMailMessage.setTo(getReceiverArray(emailPojo.getReceiver()));
        //设置邮件的抄送人
        simpleMailMessage.setCc(getReceiverArray(emailPojo.getCcPeoples()));
        //设置邮件的密送人
        simpleMailMessage.setBcc(getReceiverArray(emailPojo.getBccPeoples()));
    }

    /**
     * 处理二进制邮件的基本信息，比如需要带附件的文本邮件、HTML文件、图片邮件、模板邮件等等
     *
     * @param mimeMessageHelper：二进制文件的包装类
     * @param emailPojo:邮件pojo
     * @param isHtml:是否是HTML文件，用于区分带附件的简单文本邮件和真正的HTML文件
     * @return ：返回这个过程中是否出现异常，当出现异常时会取消邮件的发送
     */
    public boolean handleBasicInfo(MimeMessageHelper mimeMessageHelper, EmailPojo emailPojo, boolean isHtml) {
        try {
            //设置必要的邮件元素
            //设置发件人
            mimeMessageHelper.setFrom(userName);
            //设置邮件的主题
            mimeMessageHelper.setSubject(emailPojo.getSubject());
            //设置邮件的内容，区别是否是HTML邮件
            mimeMessageHelper.setText(emailPojo.getContent(), isHtml);
            //设置邮件的收件人
            mimeMessageHelper.setTo(getReceiverArray(emailPojo.getReceiver()));
            //设置非必要的邮件元素，在使用helper进行封装时，这些数据都不能够为空
            if (CollectionUtils.isEmpty(emailPojo.getCcPeoples())) {
                //设置邮件的抄送人
                mimeMessageHelper.setCc(getReceiverArray(emailPojo.getCcPeoples()));
            }
            if (CollectionUtils.isEmpty(emailPojo.getBccPeoples())) {
                //设置邮件的密送人
                mimeMessageHelper.setBcc(getReceiverArray(emailPojo.getBccPeoples()));
            }
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();
            log.error("邮件基本信息出错->{}", emailPojo.getSubject());
        }
        return false;
    }

    /**
     * 用于处理附件信息，附件需要 MimeMessage 对象
     *
     * @param mimeMessageHelper：处理附件的信息对象
     * @param subject：邮件的主题，用于日志记录
     * @param attachmentFilePaths：附件文件的路径，该路径要求可以定位到本机的一个资源
     */
    public void handleAttachment(MimeMessageHelper mimeMessageHelper, String subject, List<String> attachmentFilePaths) {
        //判断是否需要处理邮件的附件
        if (attachmentFilePaths != null && attachmentFilePaths.size() > 0) {
            FileSystemResource resource;
            String fileName;
            //循环处理邮件的附件
            for (String attachmentFilePath : attachmentFilePaths) {
                //获取该路径所对应的文件资源对象
                resource = new FileSystemResource(new File(attachmentFilePath));
                //判断该资源是否存在，当不存在时仅仅会打印一条警告日志，不会中断处理程序。
                // 也就是说在附件出现异常的情况下，邮件是可以正常发送的，所以请确定你发送的邮件附件在本机存在
                if (!resource.exists()) {
                    log.warn("邮件->{} 的附件->{} 不存在！", subject, attachmentFilePath);
                    //开启下一个资源的处理
                    continue;
                }
                //获取资源的名称
                fileName = resource.getFilename();
                try {
                    //添加附件
                    mimeMessageHelper.addAttachment(fileName, resource);
                } catch (MessagingException e) {
                    e.printStackTrace();
                    log.error("邮件->{} 添加附件->{} 出现异常->{}", subject, attachmentFilePath, e.getMessage());
                }
            }
        }
    }

    /**
     * 发送Html
     *
     * @param emailPojo:邮箱pojo
     */
    public void sendHtmlMail(EmailPojo emailPojo) {
        //检验参数：邮件主题、收件人、邮件内容必须不为空才能够保证基本的逻辑执行
        if (StringUtils.isEmpty(emailPojo.getSubject()) || StringUtils.isEmpty(emailPojo.getContent())
                || CollectionUtils.isEmpty(emailPojo.getReceiver())) {
            throw new ServiceException(ApplicationResponseCode.ERROR);
        }
        log.info("开始发送Html邮件：主题->{}，收件人->{}", emailPojo.getSubject(), emailPojo.getReceiver());
        //html
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, DEFAULT_ENCODING);
            //设置邮件的基本信息
            handleBasicInfo(helper, emailPojo.getSubject(), emailPojo.getContent(), getReceiverArray(emailPojo.getReceiver()));
            //发送邮件
            mailSender.send(mimeMessage);
            log.info("html邮件发送成功");
        } catch (MessagingException e) {
            log.error("发送邮件出错->{}", emailPojo.getSubject());
        }
        log.info("发送邮件成功: 主题->{}", emailPojo.getSubject());
    }

    /**
     * 发送html
     *
     * @param subject：邮件主题
     * @param content：邮件内容
     * @param toWho：收件人
     * @param mimeMessageHelper：二进制文件的包装类
     */
    public void handleBasicInfo(MimeMessageHelper mimeMessageHelper, String subject, String content, String[] toWho) {
        try {
            //设置发件人
            mimeMessageHelper.setFrom(userName);
            //设置邮件的主题
            mimeMessageHelper.setSubject(subject);
            //设置邮件的内容
            mimeMessageHelper.setText(content, true);
            //设置邮件的收件人
            mimeMessageHelper.setTo(toWho);
        } catch (MessagingException e) {
            log.error("html邮件基本信息出错->{}", subject);
        }
    }

    /**
     * 集合-数组转换方法
     */
    public String[] getReceiverArray(List<String> receiverList) {
        if (CollectionUtils.isEmpty(receiverList)) {
            return null;
        }
        return receiverList.toArray(new String[receiverList.size()]);
    }

}
